home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
CD ROM Paradise Collection 4
/
CD ROM Paradise Collection 4 1995 Nov.iso
/
program
/
tjgold.zip
/
INSTALL.004
/
FGUSER05.TXT
< prev
next >
Wrap
Text File
|
1995-05-29
|
28KB
|
675 lines
Mouse & Keyboard Management
"The ass loaded with gold still eats thistle"
German proverb
Introduction
The GOLDKEY unit contains all the mouse and keyboard
management routines needed to support sophisticated DOS
applications. The unit includes the following:
- Functions which wait for user input by keyboard or mouse.
- Support for mouse double-clicks, as well as keyboard mouse
combinations such as Alt-Left Button.
- Routines to hide, display, confine and move the mouse
cursor.
- Routines to get and set the state of the toggle keys, e.g.
Caps Lock, Num Lock, etc.
- Procedures to stuff keystrokes and mouse actions in the
application's keyboard buffer.
- Support for user-defined call back functions.
- Routines to change the keyboard repeat rate.
What Did the User Press (or Click)?
The primary purpose of GOLDKEY is to provide a flexible way to
pause for user mouse or keyboard activity and make it easy to then
find out what the user did! Gold uses three basic variables to
define a single user input: the keystroke or mouse action, the
mouse X coordinate and the mouse Y coordinate. These three
variables are defined in the KeyVars record as LastKey, LastX and
LastY. LastKey is a word-sized variable which is updated with a
number to indicate the key pressed. For example, if Lastkey has a
value of 27, the user pressed the Esc key, and if LastKey has a
value of 520, the user must have clicked the left mouse button. The
values in LastX and LastY indicate the location of the mouse cursor
when the button was clicked. Refer to the table on page 5-3 for a
complete list of the supported keystrokes and mouse clicks. TTT5
did not support a visible (free floating) mouse and life was much
simpler! In these good old days, keystrokes were defined in a
byte-sized variable. In Gold, a single keystroke or mouse action is
stored in a word-sized variable (KeyVars.LastKey). This change
allows a much wider range of keystrokes to be reported, and makes
Gold more flexible for international users.
Pausing for User Input
At the heart of Gold's input management routines are the
GetInput and GetInputRel procedures. The GetInput procedure pauses
program execution and waits for the user to press a key combination
or press down a mouse button. As soon as the user has pressed a key
(combination) and pressed down a mouse button, the KeyVars.LastKey,
KeyVars.LastX and KeyVars.LastY variables are updated with the
appropriate values, and program execution continues. A important
point to note is that GetInput will return as soon as a mouse
button is pressed down. In other words, this function doesn't wait
for the user to release the mouse button. By responding immediately
to a mouse down, an application can implement "dragging support"
where some task has to be performed before the button is released.
Gold, for example, uses this procedure in the window dragging
routines. However, if you don't need to support any custom dragging
operations, call the GetInputRel procedure. This procedure is very
similar to GetInput, except that the procedure only returns from a
mouse click when the user has released the mouse button. With
respect to the keyboard, GetInput and GetInputRel are identical.
After calling GetInput or GetInputRel, the program should test the
value of KeyVars.LastKey to see what the user did. If the value is
mouse-related, the program should check the values of KeyVars.LastX
and KeyVars.LastY to see where the mouse cursor was when the button
was clicked.
The following table details all the codes returned in
KeyVars.LastKey:
Keyboard codes
╔═════════════════════════════╦═════════════════════════════╗
║ Key Norm Shft Alt Ctrl ║ Key Norm Shft Alt Ctrl ║
╠═════════════════════════════╬═════════════════════════════╣
║ a 97 65 286 1 ║ F1 315 340 260 350 ║
║ b 98 66 304 2 ║ F2 316 341 361 351 ║
║ c 99 67 302 3 ║ F3 317 342 362 352 ║
║ d 100 68 288 4 ║ F4 318 343 363 353 ║
║ e 101 69 274 5 ║ F5 319 344 364 354 ║
║ f 102 70 289 6 ║ F6 320 345 365 355 ║
║ g 103 71 290 7 ║ F7 321 346 366 356 ║
║ h 104 72 291 8 ║ F8 322 347 367 357 ║
║ i 105 73 279 9 ║ F9 323 348 368 358 ║
║ j 106 74 292 10 ║ F10 324 349 369 359 ║
║ k 107 75 293 11 ║ F11 389 391 395 393 ║
║ l 208 76 294 12 ║ F12 390 392 396 394 ║
║ m 109 77 306 13 ║ Enter 13 13 284 10 ║
║ n 110 78 305 14 ║ BkSp 8 8 270 127 ║
║ o 111 79 280 15 ║ Up 328 428 408 397 ║
║ p 112 80 281 16 ║ Down 336 436 416 401 ║
║ q 113 81 272 17 ║ Left 331 431 411 371 ║
║ r 114 82 275 18 ║ Right 333 433 413 372 ║
║ s 115 83 287 19 ║ End 335 435 415 373 ║
║ t 116 84 276 20 ║ Home 327 427 407 375 ║
║ u 117 85 278 21 ║ PgUp 329 429 409 388 ║
║ v 118 86 303 22 ║ PgDn 337 437 417 374 ║
║ w 119 87 273 23 ║ Ins 338 261 418 260 ║
║ x 120 88 301 24 ║ Del 339 263 419 262 ║
║ y 121 89 277 25 ║ Tab 9 271 421 404 ║
║ z 122 90 300 26 ║ Esc 27 27 257 27 ║
║ 1 ! 49 33 376 ║ , < 44 60 307 ║
║ 2 @ 50 64 377 259 ║ . > 46 62 308 ║
║ 3 # 51 35 378 ║ / ? 47 63 309 ║
║ 4 $ 52 36 379 ║ ; : 59 58 295 ║
║ 5 % 53 37 380 ║ ' " 39 34 296 ║
║ 6 ^ 54 94 381 30 ║ [ { 91 123 282 27 ║
║ 7 & 55 38 382 ║ ] } 93 125 283 29 ║
║ 8 * 56 42 383 ║ \ | 92 124 299 28 ║
║ 9 ( 57 40 384 ║ ║
║ 0 ) 48 41 385 ║ ║
║ - _ 45 95 386 31 ║ ║
║ = + 61 43 387 ║ ║
╚═════════════════════════════╩═════════════════════════════╝
Mouse Codes
Mouse Action Code Mouse Action Code
LeftMouseDown 500 LeftMouseClick 520
LeftMouseDown+Alt 501 LeftMouseClick+Alt 521
LeftMouseDown+Ctrl 502 LeftMouseClick+Ctrl 522
LeftMouseDown+Shift 503 LeftMouseClick+Shift 523
RightMouseDown 504 RightMouseClick 524
RightMouseDown+Alt 505 RightMouseClick+Alt 525
RightMouseDown+Ctrl 506 RightMouseClick+Ctrl 526
RightMouseDown+Shift 507 RightMouseClick+Shift 527
CenterMouseDown 508 CenterMouseClick 528
CenterMouseDown+Alt 509 CenterMouseClick+Alt 529
CenterMouseDown+Ctrl 510 CenterMouseClick+Ctrl 530
CenterMouseDown+Shift 511 CenterMouseClick+Shift 531
LeftMouseDoubleClick 540 LeftDoubleClickonList 560
RightMouseDoubleClick 544
CenterMouseDoubleClick 548
Window Codes
Window Action Code
Close icon selected 600
Window moved or dragged 601
Window zoomed or stretched 602
Up arrow on V scrollbar selected 610
Down arrow on V scrollbar selected 611
Left arrow on H scrollbar selected 612
Right arrow on H scrollbar selected 613
Click on body of V scrollbar 614
Clicked on body of H scrollbar 615
Refer to Chapter 4 for a full explanation of the window codes,
and when they are generated.
Run the demo program DEMKY1.PAS to interactively see the key
codes used by Gold.
A Basic Input Loop
The following program fragment illustrates a basic input loop
which pauses for user input and then calls an appropriate
subroutine:
Finished := false
repeat
GetInputRel;
case KeyVars.LastKey of
301,113,81: Finished := true; {Alt-X,q,Q}
315: HelpEm; {F1}
337: ScrollDown20; {PgDn}
329: ScrollUp20; {PgUp}
287: SaveIt; {Alt-S}
520: begin {Left button click}
if (KeyVars.LastX <= 10)
and (KeyVars.LastY = HardVars.Depth) then
Finished := true;
end;
end;
until Finished;
Ignoring the Mouse
If you are not interested in mouse activity and want to wait
for the user to hit a standard key or key combination, you can use
the function GetKey which is defined as follows:
GetKey:char;
Waits for the user to press a key or key combination which has
a value in the range 13 to 255. The function returns the character
value of the input. Mouse activity is ignored. Behind the scenes,
GetKey uses GetInput and so the KeyVars variables LastKey, LastX
and LastY are updated.
Setting the Maximum Wait Time for Input
Gold includes the procedure GetInputWait to allow programs to
run with or without user input, and is defined as follows:
GetInputWait(WaitTime:longint);
Waits for user input via the mouse or keyboard. GetInputWait
is very similar to GetInput, except that a maximum wait time is
specified in milliseconds. The user input is recorded in the
KeyVars variables LastKey, LastX and LastY. If WaitTime expires
before user input is received, the procedure terminates and LastKey
is set to zero. If a wait time of zero is specified, GetInputWait
will not time out, i.e. it will wait indefinitely for user input.
Controlling and Managing the Mouse
Gold makes extensive use of the mouse in everything from menus
to input forms. As a developer, you gain all this power without
having to write any mouse-specific code. However, if you want to
write some custom routines which need to access the mouse, you can
take advantage of the following mouse routines:
MouseInstalled:boolean;
Returns TRUE if a mouse and mouse driver are installed,
otherwise FALSE is returned.
MouseHardwareReset;
Uses a hardware interrupt to reset the mouse to its standard
defaults. In 99% of hardware setups, a software reset (discussed
next) is faster and has the same effect.
MouseSoftwareReset;
Uses a software interrupt to set the mouse to its default
configuration. This function is called automatically when a program
(which uses GOLDKEY) is started.
MouseShow(On:boolean);
When passed TRUE, the mouse is made visible, otherwise the
mouse is hidden.
MouseMove(X,Y: integer);
Moves the mouse to the specified (X,Y) coordinate. Note that
local window or screen coordinates have no effect on this procedure
-- coordinates are always treated as global.
MouseConfine(X1,Y1,X2,Y2:integer);
Defines a rectangular region of the screen where the mouse can
move -- the user will not be able to move the mouse cursor beyond
the specified region.
MousePos(var X,Y: byte);
Updates the passed parameters with the current location of the
mouse cursor. Note that local window or screen coordinates have no
effect on this procedure -- coordinates are always reported as
globals.
MouseReleased(Button: integer; var X,Y: byte): byte;
Returns the number of times the specified button has been
released since the function was last called. Button values of 0, 1
and 2 represent the left, right and middle buttons, respectively.
The variables X and Y are updated with the mouse cursor coordinates
the last time the button was released.
MousePressed(Button: integer; var X,Y: byte): byte;
Returns the number of times the specified button has been
pressed since the function was last called. Button values of 0, 1
and 2 represent the left, right and middle buttons, respectively.
The variables X and Y are updated with the mouse cursor coordinates
the last time the button was pressed.
MouseInZone(X1,Y1,X2,Y2: byte):boolean;
Returns TRUE if the mouse cursor is situated within the
specified global coordinates.
MouseStatus(var L,C,R:boolean; var X,Y : byte);
Updates the L, C and R boolean variables to TRUE if any of the
left, center or right buttons are depressed, and updates the
variables X and Y with the current mouse location.
MouseStatusWin(var L,C,R: boolean; var X,Y: byte);
Operates like MouseStatus, except that the X and Y coordinates
are local to the window with focus.
MouseStyle(OrdChar,Attr: byte);
Sets the mouse cursor to the character represented by the
ASCII value OrdChar. The second parameter controls the display
attribute of the mouse cursor. If a zero is specified, Gold uses
the standard mouse device driver technique, which changes color
based on the underlying screen attribute to ensure maximum
contrast.
MouseRelease;
Waits for all mouse buttons to be released.
Run the demo program DEMKY2.PAS to see the mouse routines in
action.
Mouse-Related Elements of KeyVars
The following elements of the global record KeyVars affect the
mouse functions:
MouseActive
The variable KeyVars.MouseActive is set to TRUE (at program
start-up) if a mouse is installed. Gold can be forced to ignore the
mouse by setting this variable to FALSE.
DoubleDelay
Gold has to differentiate between two single clicks of the
mouse and one double click. To use an old gag, the difference is
"timing". If two single mouse clicks occur within a specified
(short) time period, a single click and a double click are
returned. The variable KeyVars.DoubleDelay specifies, in
milliseconds, the maximum elapsed time allowed between two mouse
clicks if the second click is to be reported as a double click. The
default is 350. This variable can be changed as desired.
RightHanded
The de facto standard in the industry is for the left mouse
button to be the "do it" or "enter" button, and this is Gold's
default. By setting the variable KeyVars.RightHanded to TRUE, an
application will behave as though the right mouse button is the
do-it button. If your code is written with the left mouse codes as
the standard, a simple change to this variable is all that's needed
to give right button support.
InitScrollDelay, ScrollDelay
When a user clicks on a scroll bar (in a window, list, form,
etc.) there is a momentary delay before scrolling occurs. The
variable KeyVars.InitScrollDelay sets the duration of the initial
delay, in milliseconds, and the variable KeyVars.ScrollDelay
controls the subsequent scrolling rate during scroll-bar
operations. The defaults are 350 and 50 respectively. These
variables can be changed as desired.
Accessing Ctrl, Alt and Shift
GOLDKEY supports a wide variety of special key combinations
like Alt-Backspace and Ctrl-PgUp. Sometimes, however, you may want
to know if one of the shifting keys is being pressed on its own.
GetInput and GetInputWait will not respond when Ctrl, Alt or either
Shift key is pressed.
GOLDKEY does, however, provide the following five functions to
let you check the status of the special shifting keys:
KeyShiftPressed: boolean;
Returns TRUE if either Shift key is being held down.
KeyRightShiftPressed: boolean;
Returns TRUE if the right Shift key is being held down.
KeyLeftShiftPressed: boolean;
Returns TRUE if the left Shift key is being held down.
KeyCtrlPressed:boolean;
Returns TRUE if a Ctrl key is being held down.
KeyAltPressed:boolean;
Returns TRUE if an Alt key is being held down.
Accessing Num, Scroll and Caps Lock
GOLDKEY provides the following routines for determining and
changing the status of the Num Lock, Scroll Lock and Caps Lock
keys:
KeyGetNum:boolean;
Returns TRUE if the Num Lock key is on.
KeyGetScroll:boolean;
Returns TRUE if the Scroll Lock key is on.
KeyGetCaps:boolean;
Returns TRUE if the Caps Lock key is on.
KeySetNum(On:boolean);
Pass TRUE to turn on the Num Lock key, or FALSE to turn it
off.
KeySetScroll(On:boolean);
Pass TRUE to turn on the Scroll Lock key, or FALSE to turn it
off.
KeySetCaps(On:boolean);
Pass TRUE to turn on the Caps Lock key, or FALSE to turn it
off.
Run the demo program DEMKY3.PAS to see how to access the
shifting and locking keys.
Setting the Keyboard Repeat Rate
PC keyboards support a typematic effect, i.e. holding a key
pressed down has the same effect as pressing a key multiple times.
By default, a key must be held down for about half a second before
the repetition commences, and thereafter about ten characters per
second are sent. Most users think this repeat rate is too slow
(people west of Oklahoma excepted) and Gold provides a way of
changing it.
The following three procedures alter the typematic rate on
systems with BIOS dated December 1985 or later:
KeySetFast;
Sets the typematic rate to 30 characters per second. This is
fast enough even for a New Yorker.
KeySetSlow;
Sets the typematic rate to 5 characters per second. This is
slow enough for the Post Office (just joking).
KeySetRepeatRate(Delay,Rate:byte);
This procedure allows you to explicitly set the typematic
rate. The first parameter accepts a value between 1 and 4 and
indicates the number of quarter seconds delay before the key
commences repeating. The second parameter indicates the repeat rate
and accepts a value between 0 and 31. The following table shows the
repeat rate parameter along with the resultant repeat rate:
Val Rate Val Rate Val Rate Val Rate Val Rate
0 30.0 7 16.0 14 8.6 21 4.6 28 2.5
1 26.7 8 15.0 15 8.0 22 4.3 29 2.3
2 24.0 9 13.3 16 7.5 23 4.0 30 2.1
3 21.8 10 12.0 17 6.7 24 3.7 31 2.0
4 20.0 11 10.9 18 6.0 25 3.3
5 18.5 12 10.0 19 5.5 26 3.0
6 17.1 13 9.2 20 5.0 27 2.7
Stuffing the Keyboard/Mouse Buffer
GOLDKEY uses an internal buffer for storing keystrokes and
mouse clicks. The sole purpose of this buffer is to enable you to
force characters into the buffer using the KeyStuffBuffer...
procedures. The GetInput and GetInputWait functions check to see if
there any characters in the buffer before checking the physical
mouse and keyboard.
By default the size of the buffer is 30 characters, but this
can easily be modified by changing the value of the
GStuffBufferSize constant at the top of the GOLDKEY.PAS file.
Listed below is a description of the buffer-related procedures:
KeyStuffBuffer(W:word);
Adds a keystroke to the keyboard buffer. The parameter W is
the word value of the keystroke as detailed in the table starting
on page 6.3.
KeyStuffBufferMouse(W:word;X,Y:byte);
Use this function to add a mouse click to the keyboard buffer.
The W parameter identifies the mouse action and should be in the
range 520 to 560. X and Y identify the location of the mouse cursor
corresponding with the action.
KeyStuffBufferStr(Str:string);
Stuffs characters (with ASCII values in the range 0 to 255)
into the keyboard buffer. This procedure is provided as a
convenience to save making multiple calls to KeyStuffBuffer (one
call for every character in the string).
KeyBufferSpace:word;
Returns the amount of free space available in the keyboard
buffer. If the buffer is full, any attempt to stuff additional
keystrokes will be ignored.
KeyFlushBuffer;
Erases all the entries in the application's keyboard buffer.
KeyFlushDOSBuffer;
Erases all the entries in the DOS keyboard buffer.
The keyboard buffer routines form the framework of a simple
but elegant macro facility. The demo file DEMKY5.PAS implements a
macro system and is discussed further in the (later) section Using
Keyboard Hooks.
Goodbye Keypress, Hello GkeyPressed
The standard Borland Pascal function KeyPressed returns TRUE
if there is a character waiting in DOS's keyboard buffer. In a Gold
application, you should use GKeyPressed (for Gold KeyPressed)
instead. GKeyPressed checks the internal application keyboard
buffer as well as the DOS buffer. To parody Nike, "Just use it".
If you want to check and see whether a key has been pressed,
or whether a mouse button is currently pressed, call the function
KeyorMousePressed. It functions like GkeyPressed but additionally
checks the state of the mouse buttons.
Using Keyboard Hooks
Hooks provide a way for a developer to integrate custom
routines into the heart of Gold. GOLDKEY supports two primary types
of keyboard hooks. Gold can call a procedure while the program is
idle and waiting for the user to press a key; this type of hook is
known as an idle hook (or a Post Office hook). Similarly, you can
assign a procedure which will be called every time a character is
pressed or the mouse is clicked; this type of hook is known as a
pressed hook.
Using an Idle Hook
An idle hook is an external procedure which is called
repeatedly while a program is waiting for the user to input data. A
good use for an idle hook is to display a clock, or to show the
status of the shifting keys.
All you have to do is create a procedure following some
specific rules, and then call the procedure AssignIdleHook to
instruct Gold to call the procedure during idle time.
For a procedure to be eligible as an idle hook it must adhere
to the following rules:
The procedure must be declared as a far procedure at the root
level. Refer to section Understanding Hooks in Chapter 3 for
further information.
The procedure must be declared with no (nada/zero/none) passed
parameters.
The following procedure declaration follows these rules:
{$F+}
procedure MyIdleHook;
begin
{some code}
end; {MyIdleHook}
{$F-}
The following procedure is then called to instruct Gold to
call your procedure while the application is waiting for input:
AssignIdleHook(Hook:KeyIdleHook);
Instructs Gold to call the specified procedure while pausing
for user input.
For example, the above procedure would be assigned with the
following statement:
AssignIdleHook(MyIdleHook);
The hooked procedure will be continually called while your
program is waiting for user input, so make sure that the procedure
is compact and doesn't consume too many clock cycles. If your
procedure involves too many tasks, the program will slow down
considerably during input. If you want to call an extended task,
like a background print program, you must continually checked the
GkeyPressed function and suspend your procedure when it returns
TRUE.
If subsequently, you want to remove the idle hook, execute the
following:
AssignIdleHook(NoKeyIdleHook);
The demo file DEMKY4.PAS illustrates the use of an idle hook
to display a ticking clock.
Using a Pressed Hook
A pressed hook is a procedure which is called every time a key
is pressed or a mouse button is clicked. The hooked procedure is
called before the key is processed, i.e. before the character is
returned by GetInput or GetInputWait. The hook is particularly
useful for trapping special keys like F1 for help, or for building
keyboard macros.
All you have to do is create a procedure following some
specific rules, and then call the AssignPressedHook procedure to
instruct Gold to call your procedure every time a key is pressed.
For a procedure to be eligible as a pressed hook it must
adhere to the following rules:
The procedure must be declared as a far procedure at the root
level. Refer to the section Understanding Hooks in Chapter 3
for further information.
The procedure must be declared with one variable parameter of
type word, and two variable parameters of type byte. These
parameters identify the user input, i.e. the Key, X and Y.
The following procedure declaration follows these rules:
{$F+}
procedure MyPressedHook(var Code:word;var X,Y:byte);
begin
{some code}
end; {MyPressedHook}
{$F-}
The following procedure is then called to instruct Gold to
call your procedure after each input:
AssignPressedHook(Hook:KeyPressedHook);
Instructs Gold to call the specified procedure before
processing each user input.
If, subsequently, you want to remove the pressed hook, execute
the following:
AssignPressedHook(NoKeyPressedHook);
The demo file DEMKY5.PAS shows how a pressed hook can be used
to provide macro keyboard support.
Other Neat Stuff
Here are a few more procedures included in GOLDKEY (we
couldn't decide where else to put them):
ExtendedKeyBoard:boolean;
Returns TRUE if the host system has an extended keyboard, i.e.
has 101 or more keys.
KeySetClicking(Clicking : boolean);
Call this procedure with a TRUE parameter if you want Gold to
make a tactile clicking noise every time a key is pressed, or pass
FALSE to turn off clicking.
WordToChar(W:word):char;
Gold uses a word-sized variable KeyVars.Lastkey to record user
input. Use this function translate the word-type keystroke to a
character. If the passed parameter is greater than 255, a #0 is
returned.